#pragma once

struct IEventData;

/**
All possible types of classes an event can be in.
It is recommended to make use of these when registring an event
since it can speed up the distribution process.
If you plan to create your own enums for your own event classes
it's probably a good idea to make the start with a 3 digit number (1000+)
See also EKeyPressEventClass and EKeyPressKeyEventName to prevent usage of key related event numbers.
Though you should be aware of the fact that EVENT_CLASS and EVENT_NAME are representating different things and therefore can 
take on the same values and still be differentiated.
*/
enum EVENT_CLASS
{
	/** A generic class. */ 
	EC_UNKNOWN,
	/** Events related to the physics system */
	EC_PHYSICS,
	/** Events related to the input system */
	EC_INPUT,
	/** Events related to the audio system */
	EC_AUDIO,
	/** Events related to the graphics system */
	EC_GRAPHICS,
	/** Events related to the ai system */
	EC_AI,
	/** Events related to the ENGINEframework */
	EC_FRAMEWORK,
};

/**
The actual event.
Note: if you only want to receive an update every frame, use E_UNKNOWN for performance reasons.
If you have crtitical data , you can react on the E_ONCRITICAL_ERROR event to save it or free memory a.s.o.
If you plan to create your own enums for your own events
it's probably a good idea to make the start with a 3 digit number (1000+)
0 - 0xFF is reserverd for key events. 
The bits of a 32bit integer are reserved for internal keymaps (2^0, 2^1 .. 2^31)
*/
enum EVENT_NAME
{
	/** Use this to enable per frame updates */
	E_UNKNOWN = 0x100,	// ALL
	/** Engine has been initialized */
	E_ONINIT,
	/** Engine is going to shut down */
	E_ONSHUTDOWN,
	/** A level has been loaded */
	E_ONLEVELLOADED,
	/** Something went terribly wrong, engine will shutdown */
	E_ONCRITICAL_ERROR,
};

/**
Manages events and listeners.
*/
class IEventManager
{
public:
	virtual ~IEventManager() {}


	/**
	Updates the event manager.
	@param frameTime Delta time of two frames
	*/
	virtual void Update(float frameTime) = 0;

	/**
	Registers an object to receive all events.

	@param listener		The object that wants to be registered, must be derived from IEventListener
	@param eventClass	The event class the object want's to register for, use EC_UNKNOWN for all events
	@param eventName	The event name the object wants to register for, use E_UNKNOWN to receive all events
	*/
	virtual void RegisterListener(IEventListener* listener, EVENT_CLASS eventClass = EC_UNKNOWN, EVENT_NAME eventName = E_UNKNOWN ) = 0;

	/**
	Unregisters an object.
	@param listener	The object that wants to be unregistered, must be derived from IEventListener
	*/
	virtual void UnregisterListener(IEventListener* listener) = 0;

	/**
	Queues an event that is then received by the obj that registered for it
	@param eventName		The name of the event that is to be registered
	@param eventClass		The classes to which the event applies
	@param data				Additional data the event wants to send to the listeners, must be derived from IEventData
	*/
	virtual void RegisterEvent(int eventName, int eventClass, IEventData *pData = NULL) = 0;

	/**
	Shuts down the event manager, frees leftover events and listeners,
	deallocates memory.
	*/
	virtual void ShutDown() = 0;

};